import { computed, inject, reactive, Ref } from 'vue'
import { Widget } from '@/models'
import { WidgetKind, Viewer, DragBox, MovingData, ResizeData } from '@/types'
import { EffectLock } from '@/utils'
import useSelectionDrag from './useSelectionDrag'
import DragResize from '../drag-resize/DragResize.vue'

/**
 * 控件拖拽控制
 * @param {Ref(Widget)} data 控件数据 ref
 * @param {Viewer} viewer 文档查看器
 */
export default function useWidgetCtrl(
  data: Ref<Widget>,
  draggable: Ref<boolean>,
  parent: Ref<boolean | string | undefined>,
  emit: (event: 'drag-start' | 'dragging' | 'drag-stop', ...args: any[]) => void
) {
  /** 合同控件 */
  const viewer = inject('Viewer') as Viewer

  /** 控件拖拽和调整大小锁 */
  const DnsLocker = inject('DnsLocker') as EffectLock

  /** 控件区域 */
  const Area = inject('Area') as { batchRangeWidget?: Widget | null }

  /** 是否允许跨页拖动 */
  const acrossPages = computed(() => data.value.kind === WidgetKind.NORMAL && viewer.widgetMovingAcrossPages)

  /** 多选拖拽移动 */
  const selectionDrag = useSelectionDrag(data)

  return reactive({
    /** 拖拽数据 */
    dragData: computed(() => {
      const {
        x,
        y,
        h,
        isRiding,
        displayWidth: w,
        option: { minWidth, minHeight, maxWidth, maxHeight }
      } = data.value

      return {
        x: isRiding ? 0 : x,
        y,
        w,
        h,
        minW: minWidth ?? 0,
        minH: minHeight ?? 0,
        maxW: maxWidth,
        maxH: maxHeight,
        zIndex: 1,
        zoom: viewer.zoom.level
      } as Partial<DragBox>
    }),

    /** 拖拽选项 */
    dragOptions: computed(() => {
      const { isRiding, isFixed, resizable, aspectRatio } = data.value
      const { resizeAtCenter } = data.value.option

      return {
        draggable: draggable.value && !isFixed,
        resizable,
        resizeAtCenter,
        parent: parent?.value ?? !acrossPages.value,
        axis: isRiding ? 'y' : 'both',
        // resize 句柄
        handles: ['tl', 'br', 'bl'],
        aspectRatio
      } as InstanceType<typeof DragResize>['$props']
    }),

    /** 拖拽开始 */
    dragStart(e: MouseEvent) {
      emit('drag-start', e)

      const widget = data.value
      const { selection } = viewer

      // 骑缝控件或当前控件未选中清理多选
      if (widget.isRiding || !selection.list.includes(widget)) {
        if (!(e.ctrlKey || e.metaKey)) {
          selection.clear()
          viewer.activeWidget = widget
        }

        selectionDrag.clear()
        return
      }

      /** 批量移动多选控件 */
      const list = selection.list.filter(item => item !== widget)

      selectionDrag.start(list)
    },

    /** 拖拽时同步位置 */
    dragging(e: MouseEvent, moving: MovingData) {
      let { x, y, moveX, moveY } = moving
      const widget = data.value

      // 批量控件限制范围
      if (widget.isBatch) {
        const { maxX, maxY } = widget.range

        if (x > maxX) x = maxX

        if (y > maxY) y = maxY

        /** 显示范围的临界值 */
        const RANGE_THRESHOLD = 10

        /** 显示拖拽范围 */
        const showRange =
          x < RANGE_THRESHOLD || maxX - x < RANGE_THRESHOLD || y < RANGE_THRESHOLD || maxY - y < RANGE_THRESHOLD

        Area.batchRangeWidget = showRange ? widget : null
      } else if (widget.isRiding) {
        x = 0
      }

      Object.assign(moving, { x, y })

      Object.assign(widget, { x, y })

      emit('dragging', moving)

      selectionDrag.move(moveX, moveY)
    },

    /** 拖拽结束 */
    dragStop() {
      const widget = data.value

      if (acrossPages.value) {
        widget.fixDropLocation()
      }

      widget.adjust()

      /** 更新中心点位置 */
      widget.updateOrigin()

      emit('drag-stop')

      Area.batchRangeWidget = null

      selectionDrag.stop()

      viewer.updateSortedWidgets()

      DnsLocker.lock()
    },

    /** 改变大小时同步位置和尺寸 */
    resizing(e: MouseEvent, { x, y, w, h }: ResizeData) {
      const widget = data.value
      Object.assign(widget, { x: widget.isRiding ? 0 : x, y, w, h })
    },

    /** 改变大小结束 */
    resizeStop() {
      const widget = data.value

      widget.adjust()

      viewer.updateSortedWidgets()

      DnsLocker.lock()
    }
  })
}
